package crmdna.client;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.ArrayList;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.google.gson.Gson;
import com.googlecode.objectify.ObjectifyFilter;

import crmdna.common.APIException;
import crmdna.common.APIResponse.Status;
import crmdna.user.UserEntity;

public class ClientTest {
	
	 private final LocalServiceTestHelper helper =
		        new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()
		        .setApplyAllHighRepJobPolicy());
	

    @Before
    public void setUp() {
        helper.setUp();    
    }

    @After
    public void tearDown() {  
    	ObjectifyFilter.complete();
        helper.tearDown();
    }
    
    @Test
    public void createTest() {
    	ClientEntity entity = Client.create("Isha");
    	assertEquals("isha", entity.name);
    	assertEquals("Isha", entity.displayName);    	
    	
    	entity = Client.safeGet(entity.name);
    	//should not throw exception
    	assertTrue(entity.name.equals("isha"));
    	assertTrue(entity.displayName.equals("Isha"));
    	    	
    	
    	//cannot create the same name again
    	try {
    		entity = Client.create("Isha");
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertTrue(ex.statusCode == Status.ERROR_RESOURCE_ALREADY_EXISTS);
    	}
    	
    	//cannot create in different case
    	try {
    		entity = Client.create("iSHa");
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertTrue(ex.statusCode == Status.ERROR_RESOURCE_ALREADY_EXISTS);
    	}
    	
    	//big name should get truncated
    	entity = Client.create("Isha Foundation");
    	System.out.println("entity: " + new Gson().toJson(entity));
    	assertEquals("isha fou", entity.name);
    	assertEquals("Isha Foundation", entity.displayName); 
    	
    	//cannot create same name again
    	try {
    		entity = Client.create("Isha Foundation Yoga");
    		assertTrue(false);
    	} catch (APIException e) {
			assertEquals(Status.ERROR_RESOURCE_ALREADY_EXISTS, e.statusCode);
		}    	
    }
    
    @Test
    public void safeGetTest() {
    	ClientEntity entity = Client.create("Isha");    	
    	
    	entity = Client.safeGet("isha");
    	//should not throw exception
    	assertTrue(entity.name.equals("isha"));
    	assertTrue(entity.displayName.equals("Isha"));
    	
    	//exception for non existant client
    	try {
    		entity = Client.safeGet("nonexist"); // non existant
    		assertTrue(false);
		}catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}   
    	
    	//exception when client is null
    	try {
    		entity = Client.safeGet(null); // non existant
    		assertTrue(false);
		}catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}   
    }
    
    @Test public void getTest() {
    	assertTrue(false);
    }
    
    @Test
    public void updateDisplayName() {
    	ClientEntity entity = Client.create("Isha");
    	assertEquals("isha", entity.name);    	
    	
    	entity = Client.updateDisplayName("isha", "Isha Foundation");
    	entity = Client.safeGet("isha");
    	assertTrue(entity.name.equals("isha"));
    	assertTrue(entity.displayName.equals("Isha Foundation"));    	    
    }
    
    @Test
    public void ensureValidClientTest() {
    	//throws exception is client does not exist
    	try {
    		Client.ensureValidClient("isha"); //non existant
    		assertTrue(false);
    	} catch (APIException ex) {
    		assertEquals(Status.ERROR_RESOURCE_DOES_NOT_EXIST, ex.statusCode);
		}
    	
    	Client.create("isha");
    	Client.ensureValidClient("isha");
    	//no exception
    }

    @Test
    public void getAllTest() {
    	List<ClientEntity> all = Client.getAll();
    	assertEquals(0, all.size());
    	
    	Client.create("Isha Foundation");
    	Client.create("Barclays Capital");
    	
    	all = Client.getAll();
    	assertEquals(2, all.size());
    	
    	//should be sorted by name
    	assertEquals("barclays", all.get(0).name);
    	assertEquals("Barclays Capital", all.get(0).displayName);
    	assertEquals("isha fou", all.get(1).name);
    	assertEquals("Isha Foundation", all.get(1).displayName);    	    	
    }
    
    @Test
    public void addUserTest() {
    	ClientEntity entity = Client.create("isha");    	
    	assertEquals("isha", entity.name);
    	
    	String email = "sai@ishafoundation.org";
    	Client.addUser("isha", email);
    	ObjectifyFilter.complete(); 	
    	
    	assertEquals("isha", CrmDnaUser.getClients(email).first().name);
    	
    	List<UserEntity> users = Client.getAllUsers("isha");
    	assertEquals(1, users.size());    	
    	assertTrue(users.get(0).email.equals(email));
    	
    	String email2 = "sathyanarayanant@gmail.com";
    	Client.addUser("isha", email2);
    	Client.addUser("isha", email);
    	ObjectifyFilter.complete();
    	
    	users = Client.getAllUsers("isha");
    	assertEquals(2, users.size());    	
    	assertEquals(email, users.get(0).email);
    	assertEquals(email2, users.get(1).email);    	
    }
    
    @Test
    public void deleteUserTest() {
    	ClientEntity entity = Client.create("isha");
    	assertEquals("isha", entity.name);
    	
    	String email = "sathya.t@ishafoundation.org";
    	Client.addUser("isha", email);
    	ObjectifyFilter.complete();    		   
    	
    	assertEquals("isha", CrmDnaUser.getClients(email).first().name);
    	
    	//now delete it
    	Client.deleteUser("isha", email);
    	ObjectifyFilter.complete();
    	
    	assertEquals(0, CrmDnaUser.getClients(email).size());  
    	
    	List<UserEntity> users = Client.getAllUsers("isha");
    	System.out.println("users: " + new Gson().toJson(users));
    	assertEquals(0, users.size());    
    	
    	//can delete the user again
    	Client.deleteUser("isha", email); // no exception    	
    }

    @Test
    public void getAllUsersTest() {
    	ClientEntity client = Client.create("isha");
    	assertEquals("isha", client.name);
    	
    	Client.addUser("isha", "email2@email.com");
    	Client.addUser("isha", "email3@email.com");
    	Client.addUser("isha", "email1@email.com");
    	ObjectifyFilter.complete();
    	
    	List<UserEntity> users = Client.getAllUsers("isha");
    	assertEquals(3, users.size());
    	List<UserEntity> list = new ArrayList<>();
    	list.addAll(users);
    	assertEquals("email1@email.com", list.get(0).email);
    	assertEquals("email2@email.com", list.get(1).email);
    	assertEquals("email3@email.com", list.get(2).email);    	
    }    
}
